#include <iostream>
using namespace std;

class SalaryStrategy 
{
public:
	virtual ~SalaryStrategy() {}
	virtual void pay(int year, int month)=0;
};

class EmployeeStrategy: public SalaryStrategy 
{
public:
	void pay(int year, int month) 
	{
		cout << "pay an employee's salary for " << year << "-" << month << endl;
	}
};

class ManagerStrategy: public SalaryStrategy 
{
public:
	void pay(int year, int month) 
	{
		cout << "pay a manager's salary for " << year << "-" << month << endl;
	}
};

class ExpertStrategy: public SalaryStrategy 
{
public:
	void pay(int year, int month) 
	{
		cout << "pay an expert's salary for " << year << "-" << month << endl;
	}
};

class SalesmanStrategy: public SalaryStrategy 
{
public:
	void pay(int year, int month) 
	{
		cout << "pay a salesman's salary for " << year << "-" << month << endl;
	}
};

class StrategyFactory
{
private:
    StrategyFactory() {}
public:
    static StrategyFactory* getInstance()
    {
        static StrategyFactory* instance;
        return instance;
    }
    SalaryStrategy* create(string name)
    {
        if(name=="employee") return new EmployeeStrategy();
        else if(name=="manager") return new ManagerStrategy();
        else if(name=="export") return new ExpertStrategy();
        else if(name=="salesman") return new SalesmanStrategy();
        else return NULL;
    }
};

class Employee 
{
private:
	SalaryStrategy* strategy;
public:
	void setStrategy(SalaryStrategy* strategy) 
	{
		this->strategy = strategy;
	}
	SalaryStrategy* getStrategy() 
	{
		return this->strategy;
	}
	Employee(SalaryStrategy* strategy)
	{
		this->setStrategy(strategy);
	}
	void salary(int year, int month) 
	{
		this->strategy->pay(year, month);
	}
};

int main() 
{
    StrategyFactory* factory = StrategyFactory::getInstance();
	Employee* employee;
	employee = new Employee(factory->create("employee"));
	employee->salary(2021,1);

	employee = new Employee(factory->create("manager"));
	employee->salary(2022,3);

	employee->setStrategy(factory->create("export"));
	employee->salary(2023,10);
	return 0;
}
